
// Copyright (c) 2009 Mohannad Alharthi (mohannad.harthi@gmail.com)
// All rights reserved.
// This source code is licensed under the BSD license, which can be found in
// the LICENSE.txt file.

#ifndef INCLUDE_CCOMPX_SRC_PARSER_H__
#define INCLUDE_CCOMPX_SRC_PARSER_H__

#include <stack>
#include <string>
#include <vector>

#include "ast.h"
#include "base.h"
#include "lexer.h"
#include "symbol_table.h"

#define RESERVE(lexeme, code) \
  root_symbol_table_->insert(lexeme, code)

class Parser {
 public:
  Parser(Lexer* lexer, std::vector<Message>* errors_list);
  ~Parser();

  // Parsing functions
  TranslationUnit* parse();

 private:
  void reserveKeywords();
  void error(const std::string& message_str);

  // Scan for variable and function declarations
  void scanDeclarations();

  // Get the next token from the lexer
  void getNextToken();

  void nextToken() {
    current_token_ = lexer_->getNextToken(*current_scope_table_);
  }

  // Skip until a specified token
  void skipToToken(TokenCode code);

  // Match if the given token is found, no error message is generated.
  bool matchIf(TokenCode code);
  // Matchs the token and get the next, or generate an error message.
  void match(TokenCode code);
  void match(TokenCode codes[], int n, const std::string& msg);

  // Emits a statement into the currrent block of code
  void emit(Statement* statement);

  DataTypeSpec* parseTypeSpec();
  Declaration* parseDeclaration(bool is_local_decls);
  void parseInitials(DataTypeSpec* type_spec,
                     const std::string& identifier,
                     bool is_local_decls);
  
  void parseFunction();
  BlockStatement* parseBlock();
  
  Expression* parseExpr();
  Expression* parseOrExpr();
  Expression* parseAndExpr();
  Expression* parseEqualityExpr();

  VarOperand* newTemp(DataTypeSpec* type, bool is_array);

  // Private members
  unsigned int temp_counter_;
  // Used for temporaries (Tempprarly) !
  DataTypeSpec default_type_;

  Lexer* lexer_;
  std::stack<BlockStatement*> blocks_stack_;
  std::vector<Message>* errors_list_;
  std::vector<StaticData*> data_section_;
 
  SymbolTable* current_scope_table_;
  SymbolTable* root_symbol_table_;
  
  Token current_token_;
  TranslationUnit* unit_;

  BlockStatement* current_block_;
  BlockStatement* initial_block_;

  DISALLOW_COPY_AND_ASSIGN(Parser);
};

#endif // INCLUDE_CCOMPX_SRC_PARSER_H__
